#include <GameEngine/Graphics/display_list.h>

#include <GameEngine/Graphics/openGL.h>



#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

GAMEENGINE_IMPLEMENT_RTTI(DisplayList)


//! Default constructor
DisplayList::DisplayList() : id_(0), GraphicResource() {}

//! Copy constructor
/*!
 @param rhs The display list to copy
 */
DisplayList::DisplayList(const DisplayList& rhs) : id_(rhs.id_), GraphicResource() {
	if ( id_ ) ResourceManager<ID,CONTEXTID>::instance()->reference_resource(*this);
}

//! Destructor
DisplayList::~DisplayList() {
	clean_id();
}

//! Assignment operator
/*!
 @param rhs The display list to copy
 */
DisplayList& DisplayList::operator=(const DisplayList& rhs) {
	if ( &rhs != this ) {
		ResourceManager<ID,CONTEXTID>* manager = (ResourceManager<ID,CONTEXTID>*)ResourceManager<ID,CONTEXTID>::instance();
		if ( id_ ) manager->unreference_resource(*this);
		id_ = rhs.id_;
		if ( id_ ) manager->reference_resource(*this);
	}
	return *this;
}

//! Start the display list
/*!
 @note This function allocates a new display list ID
 @note Each time the begin_display_list() function is called,
       the end_display_list() must be called as well to end
	   the packing of the instructions.
 */
void DisplayList::begin_display_list() {
	create_id();
	glNewList(id_, GL_COMPILE);
}

//! End the display list
/*!
 @note Each time the begin_display_list() function is called,
       the end_display_list() must be called as well to end
	   the packing of the instructions.
 */
void DisplayList::end_display_list() {
	glEndList();
}

//! Draw the content of the display list
/*!
 @note If the display list is not allocated, does nothing
 */
void DisplayList::draw() const {
	if ( id_ ) glCallList(id_);
}

//! Clear the content of the display list
void DisplayList::clear() {
	clean_id();
}

//! Check if the display list has been allocated
/*!
 @return True if the display list has been allocated, false otherwise
 */
bool DisplayList::initialized() const {
	return ( id_ != 0 );
}

//! Clean the previous ID
void DisplayList::clean_id() {
	// Nothing to do if ID is not allocated
	if ( id_ == 0 ) return;

	// Unreference ID from the resource manager
	ResourceManager<ID,CONTEXTID>::instance()->unreference_resource(*this);

	// Clean ID member variable
	id_ = 0;
}

//! Allocate a new ID
void DisplayList::create_id() {
	// Clean previous ID, if any
	clean_id();

	// Generate a new display list ID
	id_ = glGenLists(1);

	// Reference this ID
	ResourceManager<ID,CONTEXTID>::instance()->reference_resource(*this);
}

//! Desallocate the display list ID
void DisplayList::destroy_resource() const {
	glDeleteLists(id_, 1);
}

//! Return the display list context
DisplayList::CONTEXTID DisplayList::context() const {
	return rtti_id_;
}

//! Return the display list reference
DisplayList::ID DisplayList::reference() const {
	return id_;
}

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
